package com.taoge.webrtc.netty;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
@ChannelHandler.Sharable
@RequiredArgsConstructor
public class NettyChannelInitializer extends ChannelInitializer<SocketChannel> {

    @Value("${netty.path}")
    private String path;

    @Override
    protected void initChannel(SocketChannel channel) throws Exception {
        channel.pipeline()
                // HttpRequestDecoder和HttpResponseEncoder的一个组合，针对http协议进行编解码
                .addLast(new HttpServerCodec())
                // 分块向客户端写数据，防止发送大文件时导致内存溢出， channel.write(new ChunkedFile(new File("bigFile.mkv")))
                .addLast(new ChunkedWriteHandler())
                /*
                    心跳检测,参数说明：[长时间未读:长时间未写:长时间未读写:时间单位]~[读写是对连接本生而言，写：未向服务端发送消息，读：未收到服务端的消息]
                    readerIdleTime读空闲超时时间设定，如果channelRead()方法超过readerIdleTime时间未被调用则会触发超时事件调用userEventTrigger()方法；
                    writerIdleTime写空闲超时时间设定，如果write()方法超过writerIdleTime时间未被调用则会触发超时事件调用userEventTrigger()方法；
                    allIdleTime所有类型的空闲超时时间设定，包括读空闲和写空闲；
                    unit时间单位，包括时分秒等
                */
                .addLast(new IdleStateHandler(30, 0, 0, TimeUnit.MINUTES))
                .addLast(new IdleStateHandlerInitializer())
                // 以块的方式来写的处理器
                .addLast(new ChunkedWriteHandler())
                // 将HttpMessage和HttpContents聚合到一个完成的 FullHttpRequest或FullHttpResponse中,具体是FullHttpRequest对象还是FullHttpResponse对象取决于是请求还是响应
                // 需要放到HttpServerCodec这个处理器后面
                .addLast(new HttpObjectAggregator(8192))
                // webSocket 数据压缩扩展，当添加这个的时候WebSocketServerProtocolHandler的第三个参数需要设置成true
                .addLast(new WebSocketServerCompressionHandler())
                // 自定义处理器 - 处理 websocket 文本消息
                .addLast(new TextSocketHandler())
                // 自定义处理器 - 处理 websocket 二进制消息
                .addLast(new BinaryWebSocketFrameHandler())
                // 服务器端向外暴露的 websocket 端点，当客户端传递比较大的对象时，maxFrameSize参数的值需要调大
                .addLast(new WebSocketServerProtocolHandler(path, null, true, 65536 * 10));
    }

}

